﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using TestesFixacao.Dominio.Modelos;

namespace TestesFixacao.Dominio.Repositorios.ADO
{
    public class RepositorioAdoTeste : IRepositorioTeste
    {
        private IRepositorioQuestao _repositorioQuestao = new RepositorioAdoQuestao();

        #region Querys

        private const string SqlSelecionaPorId =
            @"SELECT    Teste.numero AS numeroTeste,
		                Teste.dataGeracao AS dataGeracaoTeste,
		                Disciplina.numero AS numeroDisciplina,
		                Disciplina.nome AS nomeDisciplina
                FROM         TBTeste AS Teste INNER JOIN
                             TBDisciplina AS Disciplina ON Teste.numeroDisciplina = Disciplina.numero
                WHERE     (Teste.numero = {0}numeroTeste)";

        private const string SqlSelecionaTodosTeste =
            @"SELECT [numero]
                    ,[dataGeracao]
                FROM [TBTeste]";

        private const string SqlSelecionaQuestoesTeste =
            @"SELECT    TBQuestao.numero,
                        TBQuestao.bimestre,
                        TBQuestao.enunciado,
                        TBQuestao.numeroMateria
                FROM   TBTeste INNER JOIN
                       TBTesteQuestao ON TBTeste.numero = TBTesteQuestao.numeroTeste INNER JOIN
                       TBQuestao ON TBTesteQuestao.numeroQuestao = TBQuestao.numero
                where TBTeste.numeroDisciplina = {0}numeroDisciplina";

        private const string SqlInsereTeste =
            @"INSERT INTO [TBTeste]
                    ([numeroDisciplina],[dataGeracao])
                VALUES
                    ({0}numeroDisciplina, {0}dataGeracao)";

        private const string SqlInsereQuestaoTeste =
            @"INSERT INTO [TBTesteQuestao]
                    ([numeroTeste],[numeroQuestao])
                VALUES
                    ({0}numeroTeste, {0}numeroQuestao)";

        private const string SqlExcluiTesteQuestao =
            @"DELETE FROM [TBTesteQuestao]
                WHERE [numeroTeste] = {0}numeroTeste";

        private const string SqlExcluiTeste =
            @"DELETE FROM [TBTeste]
                WHERE [numero] = {0}numeroTeste";

        #endregion Querys

        public void Adiciona(Teste teste)
        {
            teste.Numero = Db.Insert(SqlInsereTeste, GetParametrosTeste(teste));

            foreach (Questao questao in teste.Questoes)
            {
                Db.InsertSemRetorno(SqlInsereQuestaoTeste, GetParametrosQuestoesTeste(teste, questao));
            }
        }

        public void Edita(Teste teste)
        {
            throw new NotImplementedException();
        }

        public void Exclui(Teste teste)
        {
            try
            {
                Db.Delete(SqlExcluiTesteQuestao, new object[] { "numeroTeste", teste.Numero });
                Db.Delete(SqlExcluiTeste, new object[] { "numeroTeste", teste.Numero });
            }
            catch (Exception e)
            {
                throw new Exception("O Teste não pode ser Excluido.", e);
            }
        }

        public Teste SelecionaPorId(int id)
        {
            Teste teste = Db.Get(SqlSelecionaPorId, ConverterTesteCompleto, new object[] { "numeroTeste", id });

            teste.Questoes = Db.GetAll<Questao>(SqlSelecionaQuestoesTeste,
                ConverterQuestoesTeste, new object[] { "numeroDisciplina", teste.Disciplina.Numero });

            return teste;
        }

        public List<Teste> SelecionaTodos()
        {
            return Db.GetAll<Teste>(SqlSelecionaTodosTeste, ConverterTeste);
        }

        public Teste ConverterTeste(IDataReader reader)
        {
            Teste teste = new Teste();

            teste.Numero = Convert.ToInt32(reader["numero"]);
            teste.DataGeracao = Convert.ToDateTime(reader["dataGeracao"]);

            return teste;
        }

        public Teste ConverterTesteCompleto(IDataReader reader)
        {
            Teste teste = new Teste();

            teste.Numero = Convert.ToInt32(reader["numeroTeste"]);
            teste.DataGeracao = Convert.ToDateTime(reader["dataGeracaoTeste"]);

            Disciplina disciplina = new Disciplina();

            disciplina.Numero = Convert.ToInt32(reader["numeroDisciplina"]);
            disciplina.Nome = Convert.ToString(reader["nomeDisciplina"]);

            teste.Disciplina = disciplina;
            return teste;
        }

        public Questao ConverterQuestoesTeste(IDataReader reader)
        {
            Questao questao = new Questao();

            questao.Numero = Convert.ToInt32(reader["numero"]);
            questao.Enunciado = Convert.ToString(reader["enunciado"]);
            questao.Bimestre = Convert.ToInt32(reader["bimestre"]);
            questao.Materia = new Materia() { Numero = Convert.ToInt32(reader["numeroMateria"]) };

            return questao;
        }

        private object[] GetParametrosTeste(Teste teste)
        {
            return new object[]
            {
                "numero", teste.Numero,
                "dataGeracao", teste.DataGeracao,
                "numeroDisciplina", teste.Disciplina.Numero
            };
        }

        private object[] GetParametrosQuestoesTeste(Teste teste, Questao questao)
        {
            return new object[]
            {
                "numeroTeste", teste.Numero,
                "numeroQuestao", questao.Numero
            };
        }
    }
}